package com.cloud.sky.service;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.GifCaptcha;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.AES;
import com.cloud.sky.entity.bo.TokenInfoBO;
import com.cloud.sky.entity.common.Result;
import com.cloud.sky.entity.vo.CaptchaVO;
import com.cloud.sky.utils.AESUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import javax.script.ScriptEngine;
import java.util.Date;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author Tyrone
 * @date 2024/8/4 23:37
 */
@Service
@Slf4j
public class LoginService {
    @Autowired
    private RedisTemplate redisTemplate;
    public static final String CAPTURE_PREFIX = "captcha:";
    public static final String TOKEN_PREFIX = "token:";
    public static final String TOKEN_ADMIN_PREFIX = "0:";
    public static final String TOKEN_MEMBER_PREFIX = "1:";

    public static Integer ROLE_ADMIN = 0;
    public static Integer ROLE_MEMBER = 1;

    public CaptchaVO getCaptcha(Integer width, Integer height) {
        GifCaptcha gifCaptcha = CaptchaUtil.createGifCaptcha(width, height, 4);
        String code = gifCaptcha.getCode();
        log.info("code:{}", code);
        String uuid = UUID.randomUUID().toString();
        redisTemplate.opsForValue().set(CAPTURE_PREFIX + uuid, code, 5, TimeUnit.MINUTES);
        return new CaptchaVO(uuid, gifCaptcha.getImageBase64());
    }

    public boolean checkCaptcha(String uuid, String code) {
        String trueCode = (String) redisTemplate.opsForValue().get(CAPTURE_PREFIX + uuid);
        if (trueCode != null && StringUtils.equalsIgnoreCase(trueCode, code)) {
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

    public String getAdminToken(Long userId) {
        String token = (String) redisTemplate.opsForValue().get(TOKEN_PREFIX + TOKEN_ADMIN_PREFIX + userId);
        if (StringUtils.isEmpty(token)) {
            try {
                token = createToken(userId, ROLE_ADMIN);
                redisTemplate.opsForValue().set(TOKEN_PREFIX + TOKEN_ADMIN_PREFIX + userId, token, 7, TimeUnit.DAYS);
                return token;
            } catch (Exception e) {
                log.error("com.cloud.sky.service.LoginService.getAdminToken error", e);
            }
        }
        return token;
    }

    public String getMemberToken(Long memberId) {
        String token = (String) redisTemplate.opsForValue().get(TOKEN_PREFIX + TOKEN_MEMBER_PREFIX + memberId);
        if (StringUtils.isEmpty(token)) {
            try {
                token = createToken(memberId, ROLE_ADMIN);
                redisTemplate.opsForValue().set(TOKEN_PREFIX + TOKEN_MEMBER_PREFIX + memberId, token, 30, TimeUnit.DAYS);
                return token;
            } catch (Exception e) {
                log.error("com.cloud.sky.service.LoginService.getMemberToken error", e);
            }
        }
        return token;
    }

    /**
     * id+role+createTime+randomString(8)+expireTime;
     *
     * @return
     */
    private String createToken(Long userId, Integer role) throws Exception {
        Assert.notNull(userId, "userId is null");
        Assert.notNull(role, "role is null");
        Date date = new Date();
        long createTime = date.getTime();
        long expireTime = DateUtil.offsetDay(date, 7).getTime();
        String randomString = RandomUtil.randomString(8);
        String rawToken = "" + userId + role + createTime + randomString + expireTime;
        return AESUtil.encrypt(rawToken);
    }

    public TokenInfoBO parseToken(String token) {
        Assert.notNull(token, "token is null");
        try {
            String rawToken = AESUtil.decrypt(token);
            Date createTime = new Date(Long.parseLong(rawToken.substring(rawToken.length() - 13)));
            Date expireTime = new Date(Long.parseLong(rawToken.substring(rawToken.length() - 34, rawToken.length() - 21)));
            Integer role = Integer.valueOf(rawToken.substring(rawToken.length() - 35, rawToken.length() - 34));
            Long userId = Long.valueOf(rawToken.substring(0, rawToken.length() - 35));
            return new TokenInfoBO(userId, role, createTime, expireTime);
        } catch (Exception e) {
            log.error("com.cloud.sky.service.LoginService.parseToken error:", e);
        }
        return null;
    }

    public static void main(String[] args) throws Exception {
        LoginService loginService = new LoginService();
        String token = loginService.createToken(123123L, ROLE_ADMIN);
        System.out.println(token);
        String decrypt = AESUtil.decrypt(token);
        System.out.println(decrypt);
    }
}
